package com.tbynet.jwp.framework.kit;

import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.jfinal.kit.StrKit;

/**
 * 数据验证工具类
 *
 * @author 佰亿互联
 * @version 3.1
 * @since 2025-11-04
 */
public class ValidateKit {

    // ========== 基础验证方法 ==========

    /**
     * 使用正则表达式验证字符串
     *
     * @param str 待验证字符串
     * @param regex 正则表达式
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validate("hello", "^[a-z]+$");
     * // 返回 true
     * }</pre>
     */
    public static boolean validate(String str, String regex) {
        if(StrKit.isBlank(str)) {
            return false;
        }

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);

        return m.matches();
    }

    // ========== 格式验证方法 ==========

    /**
     * 验证密码格式（6-16位字母数字）
     *
     * @param password 密码
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validatePassword("abc123");
     * // 返回 true
     * }</pre>
     */
    public static boolean validatePassword(String password) {
        return validate(password, "^[a-zA-Z0-9]{6,16}$");
    }

    /**
     * 验证强密码格式（必须包含大小写字母和数字，8-20位）
     *
     * @param password 密码
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateStrongPassword("Abc12345");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateStrongPassword(String password) {
        return validate(password, "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d@$!%*?&]{8,20}$");
    }

    /**
     * 验证邮箱格式
     *
     * @param email 邮箱地址
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateEmail("test@example.com");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateEmail(String email) {
        return validate(email, "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$");
    }

    /**
     * 验证手机号格式（支持最新号段）
     *
     * @param mobile 手机号
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateMobile("13812345678");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateMobile(String mobile) {
        return validate(mobile, "^[1](([3][0-9])|([4][0-1,4-9])|([5][0-3,5-9])|([6][2,5-7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$");
    }

    /**
     * 验证电话号码格式
     *
     * @param phone 电话号码
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validatePhone("010-12345678");
     * // 返回 true
     * }</pre>
     */
    public static boolean validatePhone(String phone) {
        if (StrKit.isBlank(phone)) {
            return false;
        }

        if (phone.length() > 9) {
            return validate(phone, "^[0][1-9]{2,3}-[0-9]{5,10}$");// 验证带区号的
        }

        return validate(phone, "^[1-9]{1}[0-9]{5,8}$");// 验证没有区号的
    }

    /**
     * 验证身份证格式（基本格式验证）
     *
     * @param idCard 身份证号
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateIdCard("110101199001011234");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateIdCard(String idCard) {
        return validate(idCard, "(^\\d{15}$)|(^\\d{17}([0-9]|X)$)");
    }

    /**
     * 验证URL格式
     *
     * @param url URL地址
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateUrl("https://www.example.com");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateUrl(String url) {
        return validate(url, "https?://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?");
    }

    /**
     * 验证IP地址格式
     *
     * @param ip IP地址
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateIp("192.168.1.1");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateIp(String ip) {
        return validate(ip, "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
    }

    /**
     * 验证日期格式（yyyy-MM-dd）
     *
     * @param date 日期字符串
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateDate("2023-12-25");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateDate(String date) {
        return validate(date, "^\\d{4}-\\d{2}-\\d{2}$");
    }

    /**
     * 验证时间格式（HH:mm:ss）
     *
     * @param time 时间字符串
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateTime("23:59:59");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateTime(String time) {
        return validate(time, "^([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$");
    }

    // ========== 业务验证方法 ==========

    /**
     * 验证数字范围
     *
     * @param number 待验证数字
     * @param min 最小值
     * @param max 最大值
     * @return boolean 数字在范围内返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * if (ValidateKit.isValidNumberRange(age, 1, 150)) {
     *     // 年龄在有效范围内
     * }
     * }</pre>
     */
    public static boolean isValidNumberRange(Number number, Number min, Number max) {
        if (number == null) {
            return false;
        }
        double value = number.doubleValue();
        return value >= min.doubleValue() && value <= max.doubleValue();
    }

    /**
     * 验证分页参数
     *
     * @param pageNumber 页码
     * @param pageSize 每页大小
     * @return boolean 分页参数有效返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * if (ValidateKit.isValidPageParams(pageNumber, pageSize)) {
     *     PageParams pageParams = PageParams.of(pageNumber, pageSize);
     * }
     * }</pre>
     */
    public static boolean isValidPageParams(Integer pageNumber, Integer pageSize) {
        if (pageNumber == null || pageSize == null) {
            return false;
        }
        return pageNumber > 0 && pageSize > 0 && pageSize <= 1000; // 限制最大页大小
    }

    /**
     * 验证金额格式（支持两位小数）
     *
     * @param amount 金额字符串
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateAmount("123.45");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateAmount(String amount) {
        return validate(amount, "^\\d+(\\.\\d{1,2})?$");
    }

    /**
     * 验证中文姓名（2-10个中文字符）
     *
     * @param name 姓名
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateChineseName("张三");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateChineseName(String name) {
        return validate(name, "^[\\u4e00-\\u9fa5]{2,10}$");
    }

    /**
     * 验证用户名（4-20位字母数字下划线）
     *
     * @param username 用户名
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateUsername("user_123");
     * // 返回 true
     * }</pre>
     */
    public static boolean validateUsername(String username) {
        return validate(username, "^[a-zA-Z0-9_]{4,20}$");
    }

    // ========== 通用验证方法 ==========

    /**
     * 验证多个对象是否全部有效
     *
     * @param objects 待验证对象数组
     * @return boolean 所有对象都有效返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * if (ValidateKit.validateObjects(user, role, department)) {
     *     // 所有对象都有效
     * }
     * }</pre>
     */
    public static boolean validateObjects(Object... objects) {
        for (Object obj : objects) {
            if (StringKit.isNullOrInvalid(obj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 验证数组或集合不为空
     *
     * @param array 数组或集合
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.isNotEmpty(new String[]{"a", "b"});
     * // 返回 true
     * }</pre>
     */
    public static boolean isNotEmpty(Object array) {
        if (array == null) {
            return false;
        }
        if (array instanceof Object[]) {
            return ((Object[]) array).length > 0;
        }
        if (array instanceof Collection) {
            return !((Collection<?>) array).isEmpty();
        }
        if (array instanceof Map) {
            return !((Map<?, ?>) array).isEmpty();
        }
        return true;
    }

    /**
     * 验证字符串是否为布尔值
     *
     * @param str 字符串
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.isBoolean("true");
     * // 返回 true
     * }</pre>
     */
    public static boolean isBoolean(String str) {
        if (StrKit.isBlank(str)) {
            return false;
        }
        return "true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str);
    }

    /**
     * 验证文件扩展名
     *
     * @param filename 文件名
     * @param allowedExtensions 允许的扩展名数组
     * @return 验证结果
     *
     * @example
     * <pre>{@code
     * boolean result = ValidateKit.validateFileExtension("test.jpg", new String[]{"jpg", "png"});
     * // 返回 true
     * }</pre>
     */
    public static boolean validateFileExtension(String filename, String[] allowedExtensions) {
        if (StrKit.isBlank(filename) || allowedExtensions == null || allowedExtensions.length == 0) {
            return false;
        }

        String extension = getFileExtension(filename);
        for (String allowed : allowedExtensions) {
            if (allowed.equalsIgnoreCase(extension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件扩展名
     *
     * @param filename 文件名
     * @return 文件扩展名
     *
     * @example
     * <pre>{@code
     * String ext = ValidateKit.getFileExtension("test.jpg");
     * // 返回 "jpg"
     * }</pre>
     */
    public static String getFileExtension(String filename) {
        if (StrKit.isBlank(filename)) {
            return "";
        }

        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < filename.length() - 1) {
            return filename.substring(lastDotIndex + 1).toLowerCase();
        }
        return "";
    }
}